#include "tinyusb.h"
#include "USBdesc.h"
#include <stdlib.h>
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "freertos/semphr.h"
#include "tusb_cdc_acm.h"
#include "driver/gpio.h"
#include "USBdesc.h"
#include "MathHelper.h"
#include "Motor.h"
#include "myusb.h"
#include "ParaConfig.h"
// const char * TAG = "USB";
/*
    该文件用于处理usb相关的函数，注意：这个文件没有usb底层的实现，usb底层实现使用的是esp提供的tinyusb集成库，这个仅仅是处理usb的配置和初始化，usb配置了hid和cdc，最重要的hid报告描述符在components\espFFB\USBdesc.c中
*/

enum {
  ITF_NUM_HID,
  ITF_NUM_CDC_COMM,
  ITF_NUM_CDC_DATA,
};
#define ITF_NUM_TOTAL 3  // HID(1) + CDC(2个接口) = 3个接口
#define TUSB_DESC_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_HID_INOUT_DESC_LEN + TUD_CDC_DESC_LEN)

// HID端点（保持你原来的配置）
#define EPNUM_HID_OUT 0x02
#define EPNUM_HID_IN  0x82

// CDC端点（使用新的端点号）
#define EPNUM_CDC_NOTIF 0x83
#define EPNUM_CDC_OUT   0x04
#define EPNUM_CDC_IN    0x84

// USB描述符配置
const char *string_desc_arr[] = {
    (const char[]){0x09, 0x04},                // 0: 语言ID (英语)
    "ESP_FFB",                                  // 1: 制造商
    "ESP_FFB",                                  // 2: 产品名  
    "12345678",                                // 3: 序列号
    "ESP_HID",            // 4: HID接口字符串
    "ESP_CDC",                    // 5: CDC接口字符串
};

// #define TUSB_DESC_TOTAL_LEN      (TUD_CONFIG_DESC_LEN + 1 * TUD_HID_INOUT_DESC_LEN)
static const uint8_t configuration_descriptor[] = {
    // 配置描述符头
    TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, TUSB_DESC_TOTAL_LEN, 
                         TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 200),

    // HID接口描述符（保持你的INOUT配置）
    TUD_HID_INOUT_DESCRIPTOR(ITF_NUM_HID, 4, false, FFB_DESC_LENGTH, 
                           EPNUM_HID_OUT, EPNUM_HID_IN, 64, 5),

    // CDC接口描述符
    TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_COMM, 5, EPNUM_CDC_NOTIF, 8, 
                      EPNUM_CDC_OUT, EPNUM_CDC_IN, 64),
};
static uint8_t buf[CONFIG_TINYUSB_CDC_RX_BUFSIZE + 1];
void tinyusb_cdc_rx_callback(int itf, cdcacm_event_t *event)
{
    size_t rx_size = 0;
    esp_err_t ret = tinyusb_cdcacm_read(itf, buf, CONFIG_TINYUSB_CDC_RX_BUFSIZE, &rx_size);
    if (ret == ESP_OK)
    {
        if (rx_size > 0)
        {
            printf("recv!\n");
            
            protocol_process_rx_data(buf,rx_size);
        }
    }
}

void InitUSB(void)
{
    // ESP_LOGI(TAG, "USB initialization");
    const tinyusb_config_t tusb_cfg = {
        .device_descriptor = NULL,
        .string_descriptor = string_desc_arr,
        .string_descriptor_count = sizeof(string_desc_arr) / sizeof(string_desc_arr[0]),
        .external_phy = false,
        .configuration_descriptor = configuration_descriptor,
    };
    ESP_ERROR_CHECK(tinyusb_driver_install(&tusb_cfg));
    tinyusb_config_cdcacm_t acm_cfg = {
        .usb_dev = TINYUSB_USBDEV_0,
        .cdc_port = TINYUSB_CDC_ACM_0,
        .rx_unread_buf_sz = CONFIG_TINYUSB_CDC_RX_BUFSIZE, // 接收缓冲区大小
        .callback_rx = &tinyusb_cdc_rx_callback, // 注册接收回调
    };
    ESP_ERROR_CHECK(tusb_cdc_acm_init(&acm_cfg));

    // tinyusb_cdcacm_register_callback(TINYUSB_CDC_ACM_0, 
    //                                 CDC_EVENT_RX, 
    //                                 &tinyusb_cdc_rx_callback);
    
    // ESP_LOGI(TAG, "USB initialization DONE");
}


// 发送字符串
// 安全的非阻塞发送函数
esp_err_t safe_cdc_send(const uint8_t* data, size_t length)
{
    if (!tud_cdc_connected()) {
        return ESP_ERR_INVALID_STATE;
    }
    
    // 使用 write_queue 而不是 write
    int bytes_queued = tinyusb_cdcacm_write_queue(TINYUSB_CDC_ACM_0, data, length);
    
    if (bytes_queued < 0) {
        //ESP_LOGE(TAG, "Failed to queue data for CDC");
        return ESP_FAIL;
    }
    
    if (bytes_queued < length) {
        //ESP_LOGW(TAG, "Partial queue: %d/%d bytes", bytes_queued, length);
        // 可以在这里实现队列满的处理逻辑
    }
    
    // 立即尝试刷新，但不带超时（非阻塞）
    tinyusb_cdcacm_write_flush(TINYUSB_CDC_ACM_0, 0);
    
    return ESP_OK;
}

/*
配置描述符结构分析
c
static const uint8_t configuration_descriptor[] = {
    // 1. 配置描述符头
    TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, TUSB_DESC_TOTAL_LEN, 
                         TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 200),
    
    // 2. HID接口描述符
    TUD_HID_INOUT_DESCRIPTOR(ITF_NUM_HID, 4, false, FFB_DESC_LENGTH, 
                           EPNUM_HID_OUT, EPNUM_HID_IN, 64, 5),
    
    // 3. CDC接口描述符  
    TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_COMM, 5, EPNUM_CDC_NOTIF, 8, 
                      EPNUM_CDC_OUT, EPNUM_CDC_IN, 64),
};
1. 配置描述符头详解
c
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, TUSB_DESC_TOTAL_LEN, 
                     TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 200)
配置编号: 1 - 第一个配置

接口数量: ITF_NUM_TOTAL (3个接口)

字符串索引: 0 - 无配置字符串

总长度: TUSB_DESC_TOTAL_LEN - 整个配置描述符的长度

属性: TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP - 支持远程唤醒

最大功耗: 200 mA

2. HID接口描述符详解
c
TUD_HID_INOUT_DESCRIPTOR(ITF_NUM_HID, 4, false, FFB_DESC_LENGTH, 
                       EPNUM_HID_OUT, EPNUM_HID_IN, 64, 5)
接口号: ITF_NUM_HID (0) - 第一个接口

字符串索引: 4 - 使用字符串描述符数组中的第4个字符串

启动协议: false - 不使用启动协议

报告描述符长度: FFB_DESC_LENGTH - HID报告描述符的长度

输出端点: EPNUM_HID_OUT (0x02) - HID数据输出

输入端点: EPNUM_HID_IN (0x82) - HID数据输入

端点大小: 64 字节

轮询间隔: 5 ms - 高频率轮询，适合力反馈设备

3. CDC接口描述符详解
c
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_COMM, 5, EPNUM_CDC_NOTIF, 8, 
                  EPNUM_CDC_OUT, EPNUM_CDC_IN, 64)
接口号: ITF_NUM_CDC_COMM (1) - 第二个接口（通信接口）

字符串索引: 5 - 使用字符串描述符数组中的第5个字符串

通知端点: EPNUM_CDC_NOTIF (0x83) - CDC控制和状态通知

通知端点大小: 8 字节 - 用于线路编码等控制信息

数据输出端点: EPNUM_CDC_OUT (0x04) - 从主机接收数据

数据输入端点: EPNUM_CDC_IN (0x84) - 向主机发送数据

数据端点大小: 64 字节

接口分配总结
接口号	类型	功能	端点分配
0	HID	力反馈设备	OUT: 0x02, IN: 0x82
1	CDC通信	控制接口	IN: 0x83 (通知)
2	CDC数据	数据接口	OUT: 0x04, IN: 0x84
端点分配总结
端点地址	方向	用途	大小
0x02	OUT	HID数据输出	64字节
0x82	IN	HID数据输入	64字节
0x83	IN	CDC通知	8字节
0x04	OUT	CDC数据输出	64字节
0x84	IN	CDC数据输入	64字节
设备功能特点
复合设备: 同时提供HID和CDC功能

力反馈HID: 支持双向数据传输（IN和OUT端点）

虚拟串口: 通过CDC提供串行通信功能

高性能: HID使用5ms轮询间隔，适合实时力反馈

标准兼容: 符合USB CDC和HID类规范
*/